<template>
    <div class="chat-container">
        <div class="message-container">
            <div v-for="item in chats" :key="item" class="chat-content">
                <div class="question-container">
                    {{ item.question }}
                </div>
                <hr>
                <div class="ans-content">
                    {{ item.answer }}
                </div>
            </div>
            <div class="chat-content">
                <div class="question-container">
                    {{ que }}
                </div>
                <hr>
                <div class="ans-content">
                    {{ response }}
                </div>
            </div>
        </div>
        <!-- 新增固定底部容器 -->
        <div class="fixed-bottom">
            <!-- 文件上传列表 -->
            <div class="upload-list" v-if="fileQueue.length">
                <div v-for="file in fileQueue" :key="file.uid" class="upload-item">
                    <img class="file-icon" src="@/assets/文件.svg" />
                    <div class="file-info">
                        <div class="file-meta">
                            <span class="file-name">{{ file.name }}</span>
                            <span class="file-size">{{ formatSize(file.size) }}</span>
                            <span class="file-type">{{ getFileType(file.name) }}</span>
                            <span v-if="file.status === 'success'" class="status-text success">
                                <el-icon>
                                    <CircleCheck />
                                </el-icon> 上传成功
                            </span>
                            <span v-else-if="file.status === 'error'" class="status-text error">
                                <el-icon>
                                    <CircleClose />
                                </el-icon> 上传失败
                            </span>
                        </div>
                        <el-progress v-if="file.status === 'uploading'" :percentage="file.progress" :stroke-width="2"
                            class="upload-progress" :status="file.progress === 100 ? 'success' : ''" />
                    </div>
                    <div class="action-btns">
                        <div v-if="file.status === 'error'" @click.stop="retryUpload(file.uid)" class="retry-btn">
                            <el-icon>
                                <Refresh />
                            </el-icon>
                        </div>
                        <div @click.stop="handleRemove(file.uid)" class="delete-btn">
                            <el-icon>
                                <Close />
                            </el-icon>
                        </div>
                    </div>
                </div>
            </div>


            <div class="input-group">
                <!-- 使用 Element UI 的 textarea 组件 -->
                <textarea v-model="form.question" placeholder="输入您的问题" @input="adjustTextareaHeight"
                    class="rounded-input custom-textarea"></textarea>

            </div>

            <div class="button-container">
                <span style="border-left: 10px;">
                    <!-- 修改上传按钮结构 -->
                    <el-upload ref="uploadRef" multiple :auto-upload="true" :show-file-list="false"
                        :on-change="handleFileChange" :http-request="customUpload" :before-upload="beforeUploadCheck"
                        :on-error="handleUploadError">
                        <template #trigger>
                            <el-button type="primary" class="circle-button" :disabled="!userStore.getUser()">
                                <!-- 保持原有SVG图标 -->
                                <svg t="1741778487238" class="icon" viewBox="0 0 1024 1024" version="1.1"
                                    xmlns="http://www.w3.org/2000/svg" p-id="6170" width="42px">
                                    <path
                                        d="M832.715884 219.919463C832.715884 98.505593 725.04698 0 592.178971 0 463.892617 0 351.642058 109.959732 351.642058 235.955257c0 4.581655 0 11.454139 2.290828 16.035794-2.290828 4.581655-2.290828 9.163311-2.290828 16.035795v412.348993c0 89.342282 71.01566 160.357942 160.357942 160.357942s160.357942-71.01566 160.357942-160.357942v-343.624161c0-25.199105-20.61745-45.816555-45.816555-45.816555s-45.816555 20.61745-45.816555 45.816555v343.624161c0 38.944072-29.780761 68.724832-68.724832 68.724832s-68.724832-29.780761-68.724832-68.724832v-412.348993c0-4.581655 0-11.454139-2.290828-16.035795 2.290828-4.581655 2.290828-9.163311 2.290828-16.035794 0-68.724832 64.143177-144.322148 148.903803-144.322147C674.64877 91.63311 741.082774 148.903803 741.082774 219.919463c0 4.581655 0 9.163311 2.290828 11.454139 0 4.581655-2.290828 9.163311-2.290828 11.454138v481.073826c0 114.541387-103.087248 208.465324-229.082774 208.465324S282.917226 838.442953 282.917226 723.901566v-389.440716c0-25.199105-20.61745-45.816555-45.816555-45.816555s-45.816555 20.61745-45.816555 45.816555v412.348993c0 6.872483 2.290828 11.454139 2.290828 16.035795 22.908277 148.903803 155.776286 261.154362 318.425056 261.154362s295.516779-112.250559 318.425056-258.863535c2.290828-4.581655 2.290828-11.454139 2.290828-16.035794v-503.982103c0-4.581655 0-9.163311-2.290828-11.454138 2.290828-6.872483 2.290828-9.163311 2.290828-13.744967z"
                                        fill="#515151" p-id="6171"></path>
                                </svg>
                            </el-button>
                        </template>
                    </el-upload>

                    <el-button type="primary" @click="handleSubmit" class="circle-button" :disabled="!form.question">
                        <img src="@/assets/提交 .svg" alt="发送" width="43px" />
                    </el-button>
                </span>
            </div>
        </div>

    </div>
</template>

<script setup>

import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { fetchEventSource } from '@microsoft/fetch-event-source'
import { marked } from 'marked' // 引入 marked 库
import hljs from 'highlight.js';
import { useRoute, useRouter } from 'vue-router';
import { useChatStore } from '@/stores/chat';
import { useUserStore } from '@/stores/userStore'
import { getChatsApi } from '@/api/chat';
import request from '@/utils/request'
import axios from 'axios';
// 配置 marked 启用换行符转换
marked.setOptions({
    mangle: false, // 禁用标题锚点
    headerIds: false,// 禁用标题 id
    highlight: (code) => hljs.highlightAuto(code).value
})
const form = reactive({
    memoryId: '',
    question: '',
    userId: "",
    fileId: [],
    type: 0
})
const route = useRoute()
const response = ref('')
const loading = ref(false)
const statusText = ref('等待请求')
const statusType = ref('info')
const controller = ref(null)
const stop = ref(false)
// 使用 computed 将 Markdown 文本解析为 HTML
const renderedResponse = computed(() => {
    return marked.parse(response.value) // 使用明确的 parse 方法
})

const handleStop = () => {
    stop.value = true
}
const que = ref("");
const userStore = useUserStore()
const handleSubmit = async () => {
    if (loading.value) return; // 防止重复提交
    try {
        if (!flag.value) {
            // 更新 form.fileId
            form.fileId = fileQueue
                .filter(item => item.fileId) // 过滤掉未上传成功的文件
                .map(item => item.fileId);

            // 更新 form.type
            form.type = getFileType1(fileQueue);
        }


        loading.value = true;
        statusText.value = '流传输中...';
        statusType.value = 'warning';
        response.value = ''; // 清空之前的响应

        const textarea = document.querySelector('.custom-textarea');
        textarea.style.height = '30px';

        // 终止之前的请求（如果有）
        if (controller.value) {
            controller.value.abort();
        }
        controller.value = new AbortController();

        await fetchEventSource('http://localhost:8080/chat/' + route.params.memoryId, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'token': userStore.getToken()
            },
            body: JSON.stringify({
                memoryId: route.params.memoryId,
                question: form.question,
                userId: userStore.getUser()?.id,
                fileId: form.fileId,
                type: form.type
            }),
            signal: controller.value.signal,
            async onopen(response) {
                if (response.status === 401) {
                    ElMessage.error('未授权，请登录后重试');
                    controller.value?.abort();
                    loading.value = false;
                    statusText.value = '未授权';
                    statusType.value = 'danger';
                    return;
                }
            },
            onmessage(msg) {

                if (msg.data === 'end' || stop.value) { // 正确识别结束标记
                    controller.value?.abort();
                    statusText.value = '流已结束';
                    statusType.value = 'success';
                    loading.value = false;
                    stop.value = false
                } else {
                    response.value += msg.data; // 直接拼接原始数据
                }
            },
            onclose() {
                loading.value = false;
            },
            onerror(err) {
                ElMessage.error(`流错误: ${err.message}`);
                loading.value = false;
                statusText.value = '连接异常';
                statusType.value = 'danger';
            }
        });
        que.value = form.question
        form.question = ''
    } catch (err) {
        ElMessage.error(`请求失败: ${err.message}`);
        loading.value = false;
    }
    fileQueue.splice(0, fileQueue.length);
    getChats()
}

const adjustTextareaHeight = () => {
    const textarea = document.querySelector('.custom-textarea');
    // 先将高度设置为 auto 以获取内容撑开的高度
    textarea.style.height = 'auto';
    // 获取内容撑开的高度
    const scrollHeight = textarea.scrollHeight;
    if (scrollHeight < 65) {
        textarea.style.height = '65px';
    } else if (scrollHeight > 300) {
        textarea.style.height = '300px';
    } else {
        textarea.style.height = scrollHeight + 'px';
    }
}

const ChatStore = useChatStore()
const flag = ref(false)
const router = useRouter()
const getNew = async () => {
    console.log('getNew');
    const newForm = JSON.parse(route.query.question)

    console.log('newForm', newForm);
    if (newForm) {
        console.log('newForm:', newForm);
        Object.assign(form, newForm);
        console.log('form after update:', form); // 确认合并后数据
        flag.value = true
        await handleSubmit()
        ChatStore.setChat({
            memoryId: form.memoryId,
            question: que.value,
            filePath: form.filePath,
            answer: response.value
        })
    }
    router.replace({ query: {} });
}
const chats = ref([])
const getChats = async () => {
    const res = await getChatsApi(route.params.memoryId)
    console.log('res', res);
    chats.value = res.data
}


//文件
// 文件队列响应式数据
const fileQueue = reactive([])
const uploadRef = ref(null)
const cancelTokenSources = new Map() // 存储取消令牌


// 文件类型映射
const FILE_TYPE_MAP = {
    pdf: 'PDF文档',
    doc: 'Word文档',
    docx: 'Word文档',
    png: '图片',
    jpg: '图片',
    jpeg: '图片',
    txt: '文本',
    xls: 'Excel表格',
    xlsx: 'Excel表格',
    ppt: 'PowerPoint演示文稿',
    pptx: 'PowerPoint演示文稿',
}
const isImageFile = (fileName) => {
    const ext = fileName.split('.').pop().toLowerCase()
    return ['png', 'jpg', 'jpeg'].includes(ext)
}

// 文件大小单位计算
const formatSize = (bytes) => {
    const units = ['B', 'KB', 'MB', 'GB']
    let size = bytes
    let unitIndex = 0
    while (size >= 1024 && unitIndex < units.length - 1) {
        size /= 1024
        unitIndex++
    }
    return `${size.toFixed(2)} ${units[unitIndex]}`
}

// 获取文件类型
const getFileType = (fileName) =>
    FILE_TYPE_MAP[fileName.split('.').pop().toLowerCase()] || '未知文件'

// 文件校验（类型和大小）
const beforeUploadCheck = (file) => {
    const ext = file.name.split('.').pop().toLowerCase()
    if (!Object.keys(FILE_TYPE_MAP).includes(ext)) {
        ElMessage.error('不支持的文件类型')
        return false
    }
    if (file.size > 50 * 1024 * 1024) { // 50MB限制
        ElMessage.error('文件大小不能超过50MB')
        return false
    }
    return true
}

// 文件添加处理
const handleFileChange = (uploadFile) => {

    // 类型冲突校验逻辑
    if (fileQueue.length > 0) {
        const currentIsImage = isImageFile(fileQueue[0].name)
        const newIsImage = isImageFile(uploadFile.name)

        if (currentIsImage !== newIsImage) {
            ElMessage.error('图片文件不能与其他类型文件同时上传')
            return false
        }
    }

    // 原有存在性检查
    const existing = fileQueue.some(f =>
        f.raw.uid === uploadFile.raw.uid
    )


    if (!existing) {
        fileQueue.push({
            uid: uploadFile.uid,
            name: uploadFile.name,
            size: uploadFile.size,
            status: 'pending', // 初始状态设为等待
            progress: 0,
            raw: uploadFile.raw
        })
    }
}
// 计算当前文件类型（内部状态）
const queueType = computed(() => {
    if (fileQueue.length === 0) return null
    return isImageFile(fileQueue[0].name) ? 1 : 2
})
// 自定义上传逻辑
const customUpload = async ({ file, onProgress, onSuccess, onError }) => {
    const formData = new FormData()
    formData.append('file', file)

    const source = axios.CancelToken.source()
    cancelTokenSources.set(file.uid, source)

    try {
        const res = await request.post('/upload', formData, {
            headers: { 'Content-Type': 'multipart/form-data' },
            cancelToken: source.token,
            onUploadProgress: e => {
                const progress = Math.round((e.loaded / e.total) * 100)
                onProgress({ percent: progress })
                updateFileProgress(file.uid, progress)
            }
        })
        console.log('上传成功', res.details.fileId)
        const fileId = res.details.fileId
        if (fileId) {
            updateFileStatus(file.uid, 'success', fileId)
            onSuccess(res)
        } else {
            throw new Error('未获取到文件ID')
        }
    } catch (err) {
        if (!axios.isCancel(err)) {
            updateFileStatus(file.uid, 'error')
            onError(err)
        }
    } finally {
        cancelTokenSources.delete(file.uid)
    }
}

// 更新文件进度
const updateFileProgress = (uid, progress) => {
    const file = fileQueue.find(f => f.uid === uid)
    if (file) {
        file.progress = progress
        if (progress === 100) file.status = 'processing' // 进入后台处理状态
    }
}

// 更新文件状态
const updateFileStatus = (uid, status, fileId = null) => {
    const file = fileQueue.find(f => f.uid === uid)
    if (file) {
        file.status = status
        if (fileId) file.fileId = fileId
    }
}

// 文件删除处理
const handleRemove = (uid) => {
    const source = cancelTokenSources.get(uid)
    if (source) source.cancel('用户取消上传')

    const index = fileQueue.findIndex(f => f.uid === uid)
    if (index !== -1) fileQueue.splice(index, 1)
}

// 上传失败统一处理
const handleUploadError = (err) => {
    ElMessage.error(`上传失败: ${err.message}`)
}

// 重试上传
const retryUpload = (uid) => {
    const file = fileQueue.find(f => f.uid === uid)
    if (file) {
        file.status = 'uploading'
        file.progress = 0
        uploadRef.value.abort(file) // 调用element的方法重新提交
    }
}

// 获取文件类型（1: 图片，2: 其他）
const getFileType1 = (fileQueue) => {
    if (fileQueue.length === 0) return 0; // 无文件
    return isImageFile(fileQueue[0].name) ? 1 : 2;
};

onMounted(() => {
    getNew()
    if (!route.query.question) {
        getChats()
    }
})

</script>

<style scoped>
/* 聊天主容器 */
.chat-container {
    height: 100vh;
    padding-bottom: 100px;
    /* 底部输入栏高度 */
}

/* 消息滚动容器 */
.message-container {
    height: calc(100vh - 120px);
    overflow-y: auto;
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
}

/* 聊天内容卡片 */
.chat-content {
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    margin-bottom: 20px;
    padding: 16px;
}

/* 问题样式 */
.question-container {
    font-size: 16px;
    color: #333;
    line-height: 1.6;
    padding: 12px;
    background: #f8f9fa;
    border-radius: 8px;
}

/* 答案样式 */
.ans-content {
    font-size: 15px;
    color: #666;
    line-height: 1.7;
    padding: 12px;
    white-space: pre-wrap;
}

/* 分割线 */
hr {
    border: 0;
    height: 1px;
    background: #eee;
    margin: 12px 0;
}

/* 适配移动端 */
@media (max-width: 768px) {
    .message-container {
        padding: 10px;
    }

    .chat-content {
        border-radius: 8px;
    }
}

/* 底部输入栏定位修正 */
.fixed-bottom {
    position: fixed;
    bottom: 20px;
    left: 300px;
    /* 侧边栏宽度 */
    right: 20px;
    max-width: calc(100% - 320px);
    /* 300 + 20 padding */
    margin: 0 auto;
    background: #fff;
    border-top: 1px solid #eee;
    padding: 12px 20px;
    border-radius: 12px;
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
    display: flex;
    gap: 12px;
    z-index: 999;
}

/* 输入框样式优化 */
.input-group {
    flex: 1;
    background: #f8f9fa;
    border-radius: 24px;
    padding: 8px 16px;
}

.custom-textarea {
    width: 100% !important;
    border: none !important;
    background: transparent !important;
    font-size: 16px !important;
    line-height: 1.5 !important;
    resize: none !important;
}

.custom-textarea:focus {
    outline: none !important;
    border: none !important;
}

/* 按钮美化 */
.circle-button {
    border-radius: 50% !important;
    width: 50px !important;
    height: 50px !important;
    border: 1px solid #ddd !important;
    padding: 0 !important;
    transition: all 0.2s !important;
}

.circle-button:hover {
    transform: scale(1.05);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* 用户信息区域 */
.user-info-box {
    margin-top: auto;
    padding: 20px 0;
    text-align: center;
    border-top: 1px solid #eee;
}

/* 聊天列表容器 */
.chat-list-container {
    flex: 1;
    overflow-y: auto;
    margin: 20px -20px;
    padding: 0 20px;
}


.upload-list {
    margin-bottom: 12px;
    max-height: 200px;
    overflow-y: auto;
}

.upload-item {
    display: flex;
    align-items: center;
    padding: 8px;
    background: #f5f7fa;
    border-radius: 4px;
    margin-bottom: 8px;
}

.file-icon {
    width: 32px;
    height: 32px;
    margin-right: 12px;
}

.file-info {
    flex: 1;
    min-width: 0;
}

.file-meta {
    display: flex;
    justify-content: space-between;
    margin-bottom: 4px;
    font-size: 12px;
}

.file-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-right: 8px;
}

.file-size {
    color: #909399;
    margin-right: 8px;
}

.file-type {
    color: #409eff;
}

.upload-progress {
    margin-top: 4px;
}

.hidden-upload {
    display: none;
}

/* 在原有样式基础上添加删除按钮相关样式 */
.upload-item {
    position: relative;
    /* 为删除按钮定位提供参照 */
    padding-right: 32px;
    /* 为删除按钮留出空间 */
}

.delete-btn {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    cursor: pointer;
    color: #ff4d4f;
    opacity: 0.8;
    transition: all 0.2s;
    font-size: 16px;
    background: rgba(255, 255, 255, 0.8);
    border-radius: 50%;
    padding: 4px;
    display: flex;
}

.delete-btn:hover {
    opacity: 1;
    transform: translateY(-50%) scale(1.1);
    color: #ff1f22;
}

/* 在深色背景下的适配 */
.upload-item:hover .delete-btn {
    background: rgba(0, 0, 0, 0.04);
}

/* 移动端适配 */
@media (max-width: 768px) {
    .delete-btn {
        right: 4px;
        padding: 2px;
    }
}
</style>